package com.youlu.campus.service.card;

import com.alibaba.fastjson.JSONObject;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.IdGeneratorUtils;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.WechatMerchantConfig;
import com.youlu.campus.entity.card.dto.CardCateQueryDTO;
import com.youlu.campus.entity.card.dto.CardOrderCreateDTO;
import com.youlu.campus.entity.card.dto.CardOrderQueryDTO;
import com.youlu.campus.entity.card.entity.*;
import com.youlu.campus.entity.card.vo.*;
import com.youlu.campus.entity.course.dto.GoodsOrderDTO;
import com.youlu.campus.service.course.TxThirdService;
import com.youlu.campus.service.course.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : [dengbo]
 * @className : CardService
 * @description : [视频卡片服务]
 * @createTime : [2022/12/17 15:31]
 */
@Service
@Slf4j
public class TsCardService {

    private static final String THIRD_REDEE_CODE_URL = "https://lx.huilankeji.cn/m/exchanges/query?code=";
    @Autowired
    private MongoTemplate mongoTemplate;

    @Resource(name = "masterMongoTemplate")
    private MongoTemplate masterMongoTemplate;

    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private TxThirdService txThirdService;

    public List<CardCateResultVo> getFistCateList() {
        Query query = new Query();
        query.addCriteria(Criteria.where("parentId").is("0"));
        query.addCriteria(Criteria.where("deleted").is(false));
        List<CardCategory> categories = mongoTemplate.find(query, CardCategory.class);
        Set<String> cateIdList = categories.stream().map(CardCategory::getId).collect(Collectors.toSet());
        List<CardGoods> goods = mongoTemplate.find(new Query(Criteria.where("firstCateId").in(cateIdList)), CardGoods.class);
        //Map<String, IntSummaryStatistics> map = goods.stream().collect(Collectors.groupingBy(CardGoods::getFirstCateId, Collectors.summarizingInt(CardGoods::getSalePrice)));
        Map<String, Optional<CardGoods>> map = goods.stream().filter(item -> item.getOnSale() && !item.getDeleted())
                .collect(Collectors.groupingBy(CardGoods::getFirstCateId, Collectors.minBy(Comparator.comparing(CardGoods::getSalePrice))));
        List<CardCateResultVo> results = categories.stream().sorted(Comparator.comparing(CardCategory::getPriority).reversed())
                .map(item -> {
                    CardCateResultVo result = new CardCateResultVo();
                    result.setCateId(item.getId());
                    result.setCateName(item.getCateName());
                    result.setCateImage(item.getCateImage());
                    Optional<CardGoods> optional = map.get(item.getId());
                    if (optional != null && optional.isPresent()) {
                        CardGoods cardGoods = optional.get();
                        result.setSalePrice(cardGoods.getSalePrice());
                        result.setOfficialPrice(cardGoods.getOfficialPrice());
                    }
                    result.setPopupQrcode(item.getPopupQrcode());
                    return result;
                })
                .collect(Collectors.toList());
        return results;
    }

    public CardCateDetailVo getFistCateDetail(CardCateQueryDTO dto) {
        CardCategory category = mongoTemplate.findById(dto.getCateId(), CardCategory.class);
        if (category == null) {
            throw new BusinessException("分类信息不存在");
        }
        CardCateDetailVo detailVo = new CardCateDetailVo();
        detailVo.setCateId(dto.getCateId());
        detailVo.setCateName(category.getCateName());
        detailVo.setCateImage(category.getCateImage());
        detailVo.setAccountTips(category.getAccountTips());
        detailVo.setPopupQrcode(category.getPopupQrcode());
        Query query = new Query();
        query.addCriteria(Criteria.where("parentId").is(dto.getCateId()));
        query.addCriteria(Criteria.where("deleted").is(false));
        List<CardCategory> categories = mongoTemplate.find(query, CardCategory.class);
        Set<String> cateIdList = categories.stream().map(CardCategory::getId).collect(Collectors.toSet());
        //查询商品列表
        Query goodsQuery = new Query();
        goodsQuery.addCriteria(Criteria.where("firstCateId").is(dto.getCateId()));
        goodsQuery.addCriteria(Criteria.where("secondCateId").in(cateIdList));
        goodsQuery.addCriteria(Criteria.where("onSale").is(true));
        goodsQuery.addCriteria(Criteria.where("deleted").is(false));
        List<CardGoods> goodsList = mongoTemplate.find(goodsQuery, CardGoods.class);
        Map<String, List<CardCateGoodsVo>> goodsMap = goodsList.stream().map(item -> {
            CardCateGoodsVo goodsVo = new CardCateGoodsVo();
            goodsVo.setGoodsName(item.getGoodsName());
            goodsVo.setGoodsType(item.getGoodsType());
            goodsVo.setGoodsId(item.getId());
            goodsVo.setPrice(item.getPrice());
            goodsVo.setFirstCateId(item.getFirstCateId());
            goodsVo.setSecondCateId(item.getSecondCateId());
            goodsVo.setOfficialPrice(item.getOfficialPrice());
            goodsVo.setSalePrice(item.getSalePrice());
            goodsVo.setPriority(item.getPriority());
            goodsVo.setThirdGoodsCode(item.getThirdGoodsCode());
            return goodsVo;
        }).collect(Collectors.groupingBy(CardCateGoodsVo::getSecondCateId));
        List<CardCateResultVo> results = categories.stream().sorted(Comparator.comparing(CardCategory::getPriority).reversed()).map(item -> {
            CardCateResultVo result = new CardCateResultVo();
            result.setCateId(item.getId());
            result.setCateName(item.getCateName());
            result.setCateImage(item.getCateImage());
            result.setDescription(item.getDescription());
            //商品列表
            List<CardCateGoodsVo> goodsVos = goodsMap.get(result.getCateId());
            if (CollectionUtils.isNotEmpty(goodsVos)) {
                goodsVos = goodsVos.stream().sorted(Comparator.comparing(CardCateGoodsVo::getPriority).reversed()).collect(Collectors.toList());
            } else {
                goodsVos = new ArrayList<>();
            }
            result.setGoodsList(goodsVos);
            return result;
        }).collect(Collectors.toList());
        detailVo.setCateList(results);
        return detailVo;
    }

    public CardOrderVo createTsOrder(CardOrderCreateDTO dto) {
        CardGoods cardGoods = mongoTemplate.findOne(new Query(Criteria.where("id").is(dto.getGoodsId())), CardGoods.class);
        if (cardGoods == null) {
            throw new BusinessException("商品信息不存在");
        }
        if (!cardGoods.getOnSale()) {
            throw new BusinessException("商品已下架");
        }
        UserPO userPO = dto.getUserPO();
        CardOrder cardOrder = buildCardOrder(dto, cardGoods);
        // 获取商户信息
        WechatMerchantConfig merchantInfo = wechatPayService.getRandomMerchant(userPO.getAppId());
        cardOrder.setMerchantId(merchantInfo.getMerchantId());
        cardOrder.setMerchantName(merchantInfo.getMerchantName());

        // 获取支付凭证
        Triple<Boolean, Object, String> result = wechatPayService.unifiedOrder(buildGoodsOrderParam(cardOrder), merchantInfo, dto.getNotifyUrl());
        if (!result.getLeft()) {
            throw new BusinessException(result.getRight());
        }
        // 创建新的订单
        cardOrder.setPayInfo(result.getMiddle());
        inserCardOrder(cardOrder);
        CardOrderVo vo = new CardOrderVo();
        vo.setPayInfo(result.getMiddle());
        return vo;
    }

    public List<CardOrder> getOrderList(CardOrderQueryDTO dto) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(dto.getUserId()));
        if (dto.getStatus() != null && dto.getStatus() >= 0) {
            query.addCriteria(Criteria.where("status").is(dto.getStatus()));
        }
        query.with(Sort.by(Sort.Order.desc("id")));
        List<CardOrder> orders = mongoTemplate.find(query, CardOrder.class);
        Set<String> fcateIdList = orders.stream().map(CardOrder::getFirstCateId).collect(Collectors.toSet());
        List<CardCategory> categories = mongoTemplate.find(new Query(Criteria.where("id").in(fcateIdList)), CardCategory.class);
        Map<String, String> imgMap = categories.stream().collect(Collectors.toMap(CardCategory::getId, CardCategory::getCateImage, (o1, o2) -> o2));
        orders.stream().forEach(item -> {
            if (imgMap.get(item.getFirstCateId()) != null) {
                item.setCateImage(imgMap.get(item.getFirstCateId()));
            }
        });
        return orders;
    }

    public CardOrder inserCardOrder(CardOrder order) {
        mongoTemplate.insert(order);
        return order;
    }

    public CardOrder buildCardOrder(CardOrderCreateDTO dto, CardGoods goods) {
        UserPO userPO = dto.getUserPO();
        //获取支付凭证
        CardOrder cardOrder = new CardOrder();
        cardOrder.setUserId(userPO.getId());
        cardOrder.setStatus(0);
        cardOrder.setPrice(goods.getSalePrice());
        cardOrder.setName(goods.getGoodsName());
        cardOrder.setChargeAccount(dto.getChargeAccount());
        cardOrder.setThirdGoodsCode(goods.getThirdGoodsCode());
        cardOrder.setActivityId(dto.getActivityId());
        cardOrder.setFirstCateId(goods.getFirstCateId());
        cardOrder.setSecondCateId(goods.getSecondCateId());
        cardOrder.setCreatedTime(new Date());
        String orderNo = IdGeneratorUtils.generateVideoNo();
        cardOrder.setOrderNo(orderNo);
        cardOrder.setAppId(userPO.getAppId());
        cardOrder.setPlatform(userPO.getCurrentPlatform());
        cardOrder.setOpenId(userPO.getOpenId());
        cardOrder.setUnionId(userPO.getUnionId());
        cardOrder.setPhone(userPO.getMobile());
        cardOrder.setNickName(userPO.getNickName());
        cardOrder.setClientIp(dto.getClientIp());
        LocalDateTime now = LocalDateTime.now();
        cardOrder.setStartTime(now);
        return cardOrder;
    }

    public GoodsOrderDTO buildGoodsOrderParam(CardOrder order) {
        GoodsOrderDTO dto = new GoodsOrderDTO();
        dto.setOrderNo(order.getOrderNo());
        dto.setClientIp(order.getClientIp());
        dto.setOpenId(order.getOpenId());
        dto.setGoodsName(order.getName());
        dto.setPrice(order.getPrice());
        dto.setUserId(order.getUserId());
        dto.setAppId(order.getAppId());
        return dto;
    }

    /**
     * 处理支付回调
     *
     * @param orderNo
     * @param transactionId
     */
    public void dealOrderPaySuccess(String orderNo, String transactionId) {
        CardOrder order = mongoTemplate.findOne((new Query(Criteria.where("orderNo").is(orderNo))), CardOrder.class);
        if (order == null) {
            log.warn("dealOrderPaySuccess,orderNo:{} not exist", orderNo);
            return;
        }
        int status = order.getStatus();
        log.info("before deal order orderNo:{} orderStatus:{}", orderNo, status);
        switch (status) {
            case 2:
                log.warn("dealOrderPaySuccess,orderNo:{} has charged", orderNo);
                return;
            case 1:
                log.warn("dealOrderPaySuccess,orderNo:{} charging ", orderNo);
                return;
            case 3:
                log.warn("dealOrderPaySuccess,orderNo:{} has refund success", orderNo);
                return;
            case 0:
                try {
                    //第三方充值
                    Map<String, Object> re = txThirdService.createOrder(order.getThirdGoodsCode(), order.getChargeAccount(), orderNo);
                    log.info("orderNo:{} tx deal order result:{}", orderNo, re);
                    String thirdStatus = re.get("status").toString();
                    if ("4".equals(thirdStatus)) {
                        // 处理失败退款
                        order.setStatus(3);
                        Object refundReason = re.get("status_info");
                        order.setRefundReason(refundReason == null ? "第三方处理失败" : refundReason);
                    } else if ("3".equals(thirdStatus)) {
                        // 处理成功，充值成功
                        order.setStatus(2);
                    } else {
                        // 处理中，变更充值中
                        order.setStatus(1);
                    }
                    order.setThirdOrderId(re.get("order_id").toString());
                } catch (BusinessException e) {
                    // 调用异常，退款
                    order.setStatus(3);
                    order.setRefundReason(e.getMessage());
                } catch (Exception e) {
                    log.error("tx create order error", e);
                    // 调用异常，退款
                    order.setStatus(3);
                    order.setRefundReason(e.getMessage());
                }
                // 更新订单状态
                order.setPayTime(LocalDateTime.now());
                order.setTransactionId(transactionId);
                // 退款
                if (order.getStatus() == 3) {
                    cardOrderRefund(order);
                    return;
                }
                //支付成功
                mongoTemplate.save(order);
                log.info("dealOrderPaySuccess,orderNo:{} pay success", orderNo);
                return;
            default:
                break;
        }
    }

    public GoodsOrderDTO buildRefundOrderParam(CardOrder order) {
        GoodsOrderDTO dto = new GoodsOrderDTO();
        dto.setRefundNo(order.getRefundNo());
        dto.setOrderNo(order.getOrderNo());
        dto.setOpenId(order.getOpenId());
        dto.setPrice(order.getPrice());
        dto.setRefundPrice(order.getPrice());
        dto.setUserId(order.getUserId());
        dto.setAppId(order.getAppId());
        return dto;
    }

    /**
     * params.get("status") 三方通知状态
     * 1 等待处理
     * 2 正在处理
     * 3 处理成功
     * 4 处理失败
     * @param params
     */
    public void cardPayNotify(Map<String, String> params) {
        String orderNo = params.get("merchant_order_id");
        CardOrder order = mongoTemplate.findOne(new Query(Criteria.where("orderNo").is(orderNo)), CardOrder.class);
        if (order == null) {
            log.warn("dealOrderPaySuccess,orderNo:{} not exist", order.getOrderNo());
            return;
        }
        // 充值成功或者退款
        if (order.getStatus() == 2 || order.getStatus() == 3) {
            log.info("complete or refund,orderNo:{}", order.getOrderNo());
            return;
        }
        if (order.getStatus() == 1) {
            String status = params.get("status");
            // 处理成功
            if ("3".equals(status)) {
                // 更新订单充值成功
                order.setStatus(2);
                mongoTemplate.save(order);
            } else if ("4".equals(status)) {
                String refundReason = params.get("status_info");
                order.setRefundReason(refundReason == null ? "第三方处理失败" : refundReason);
                cardOrderRefund(order);
                return;
            }
        } else if (order.getStatus() == 4) {
            // 账户余额不足处理失败
            cardOrderRefund(order);
        }
    }

    public void cardOrderRefund(CardOrder order) {
        // 获取商户信息
        WechatMerchantConfig merchantInfo = wechatPayService.getWechatMerchantConfigById(order.getMerchantId());
        if (StringUtils.isBlank(order.getRefundNo())) {
            String refundOrderNo = IdGeneratorUtils.generateVideoRefundNo();
            order.setRefundNo(refundOrderNo);
        }
        // 退款
        Triple<Boolean, Map, String> re = wechatPayService.refund(buildRefundOrderParam(order), merchantInfo);
        log.info("orderNo:{} card refund result:{}", order.getOrderNo(), re);
        if (re.getLeft()) {
            order.setStatus(3);
            order.setRefundTime(LocalDateTime.now());
        } else {
            order.setStatus(4);
        }
        order.setRefundInfo(re.getMiddle());
        mongoTemplate.save(order);
    }

    public void cardPriceUpdateNotify(Map<String, String> params) {
        String merchantId = params.get("merchant_id");
        String thirdGoodsCode = params.get("product_id");
        Query query = Query.query(Criteria.where("thirdGoodsCode").is(thirdGoodsCode));
        CardGoods goods = mongoTemplate.findOne(query, CardGoods.class);
        if (goods == null) {
            log.warn("goodsId:{} goods info not exist", thirdGoodsCode);
            return;
        }
        Integer oldOfficialPrice = goods.getOfficialPrice();
        BigDecimal currentPrice = new BigDecimal(params.get("after_price")).multiply(BigDecimal.valueOf(100));
        goods.setPrice(currentPrice.intValue());
        BigDecimal salePrice = currentPrice.multiply(new BigDecimal("1.1")).setScale(0, RoundingMode.HALF_UP);
        goods.setSalePrice(salePrice.intValue());
        Integer officialPrice = new BigDecimal(params.get("official_price")).multiply(BigDecimal.valueOf(100)).intValue();
        goods.setOfficialPrice(officialPrice);
        Integer oldPrice = new BigDecimal(params.get("before_price")).multiply(BigDecimal.valueOf(100)).intValue();
        log.info("goods code:{} old-price:{}", thirdGoodsCode, oldPrice);
        Update update = new Update();
        update.set("price", goods.getPrice());
        update.set("salePrice", goods.getSalePrice());
        update.set("officialPrice", goods.getOfficialPrice());
        mongoTemplate.updateMulti(query, update, CardGoods.class);
        //添加价格变更日志
        CardPriceUpdateLog log = new CardPriceUpdateLog();
        log.setMerchantId(merchantId);
        log.setProductId(thirdGoodsCode);
        log.setProductName(params.get("product_name"));
        log.setProductType(params.get("product_type"));
        log.setAfterPrice(goods.getPrice());
        log.setBeforPrice(oldPrice);
        log.setOfficialPrice(goods.getOfficialPrice());
        log.setOldOfficialPrice(oldOfficialPrice);
        log.setCreatedTime(new Date());
        mongoTemplate.save(log);
    }

    public void disuseRedeemCode(OrderInfo orderInfo) {
        List<VipRedeemCodeRecord> list = mongoTemplate.find(new Query(Criteria.where("orderNo").is(orderInfo.getOrderNo())), VipRedeemCodeRecord.class);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        VipRedeemCodeRecord record = list.get(0);
        if (record == null || record.getStartTime() == null) {
            return;
        }
        if (record.getStartTime().isBefore(LocalDateTime.now())) {
            //12小时全部退款
            if (orderInfo.getRefundType() != null && orderInfo.getRefundType() == 0) {
                log.info("orderNo:{} more 12 hour not allow all refund", orderInfo.getOrderNo());
                throw new BusinessException("当前订单包含视频卡类等虚拟商品，用户可能已经兑换，不能全部退款，请选择部分退款");
            }
            log.info("orderNo:{} more 12 hour allow part refund", orderInfo.getOrderNo());
            return;
        }
        List<String> idList = new ArrayList<>();
        Set<String> codeList = new HashSet<>();
        list.forEach(item -> {
            if (item.getStatus() == 0) {
                idList.add(item.getId());
                codeList.add(item.getRedeemCode());
            }
        });
        if (CollectionUtils.isNotEmpty(codeList)) {
            // 作废兑换码
            txThirdService.cancelRedeemCode(codeList);
            // 更新状态
            Query query = new Query();
            query.addCriteria(Criteria.where("id").in(idList));
            Update update = new Update();
            update.set("status", 1);
            Date date = new Date();
            update.set("disuseTime", new Date());
            update.set("updatedTime", date);
            mongoTemplate.updateMulti(query, update, VipRedeemCodeRecord.class);
        }
    }

    public void makeRedeemCode(String orderNo) {
        LocalDateTime dateTime = LocalDateTime.now();
        log.info("make redeem code orderNo:{},time:{}", orderNo, dateTime);
        // 生成兑换码
        List<OOrderInfo> orderInfos = mongoTemplate.find(new Query(Criteria.where("orderNo").is(orderNo)), OOrderInfo.class);
        if (org.springframework.util.CollectionUtils.isEmpty(orderInfos)) {
            return;
        }
        long num = orderInfos.stream().filter(item -> item.getHasVirtualGoods() != null && item.getHasVirtualGoods()).count();
        log.info("orderNo:{} make redeem code num:{}", orderNo, num);
        if (num <= 0) {
            return;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        orderInfos.forEach(item -> {
            if (item.getHasVirtualGoods() == null || !item.getHasVirtualGoods()) {
                return;
            }
            VipGoods vipGoods = mongoTemplate.findById(item.getVirtualGoodsId(), VipGoods.class);
            log.info("query vip goods info:{},sub orderNo:{}", vipGoods, item.getOOrderNo());
            if (vipGoods == null) {
                // 添加兑换码更新失败记录
                addFailRecord(item);
                return;
            }
            LocalDateTime startDate = dateTime.plusHours(vipGoods.getExpireAfterHour());
            String startTime = formatter.format(startDate);
            LocalDateTime endDate = startDate.plusDays(vipGoods.getExpireDay());
            String entTime = formatter.format(endDate);
            VipRedeemCodeRecord record = queryRedeemCodeByOrderNo(item.getOOrderNo());
            if (record != null && StringUtils.isNotBlank(record.getRedeemCode())) {
                return;
            }
            try {
                Map<String, Object> re = txThirdService.generateRedeemCode(item.getVirtualGoodsCode(), 1, startTime, entTime);
                String codeListStr = (String) re.get("code_list");
                List<String> codeList = JSONObject.parseObject(codeListStr, List.class);
                if (CollectionUtils.isNotEmpty(codeList)) {
                    // 添加成功兑换码记录
                    updateRedeemCodeRecord(record, item, vipGoods, codeList.get(0), startDate, endDate);
                    return;
                }
            } catch (BusinessException e) {
                log.error("sub orderNo:{} make redeem code fail", item.getOOrderNo());
            } catch (Exception e) {
                log.error("sub orderNo:{} make redeem code error", item.getOOrderNo(), e);
            }
            updateRedeemCodeRecord(record, item, vipGoods, "", startDate, endDate);
        });
    }

    public VipRedeemCodeRecord queryRedeemCodeByOrderNo(String subOrderNo) {
        Query query = new Query(Criteria.where("subOrderNo").is(subOrderNo));
        VipRedeemCodeRecord record = masterMongoTemplate.findOne(query, VipRedeemCodeRecord.class);
        return record;
    }

    public void updateRedeemCodeRecord(VipRedeemCodeRecord record, OOrderInfo oOrderInfo, VipGoods vipGoods, String redeemCode, LocalDateTime startDate, LocalDateTime endDate) {
        if (record == null) {
            addRedeemCodeRecord(oOrderInfo, vipGoods, redeemCode, startDate, endDate);
            return;
        }
        if (record.getStatus() == 2 && StringUtils.isNotBlank(redeemCode)) {
            log.info("sub orderNo:{} make redeem code again", oOrderInfo.getOOrderNo());
            record.setRedeemCode(redeemCode);
            record.setStatus(0);
            record.setUpdatedTime(new Date());
            mongoTemplate.save(record);
        }
    }

    public void addRedeemCodeRecord(OOrderInfo oOrderInfo, VipGoods vipGoods, String redeemCode, LocalDateTime startDate, LocalDateTime endDate) {
        VipRedeemCodeRecord record = new VipRedeemCodeRecord();
        record.setVirtualGoodsCode(oOrderInfo.getVirtualGoodsCode());
        record.setUserId(oOrderInfo.getAccountInfoId());
        record.setVirtualGoodsName(oOrderInfo.getVirtualGoodsName());
        record.setVirtualGoodsId(oOrderInfo.getVirtualGoodsId());
        record.setSubOrderNo(oOrderInfo.getOOrderNo());
        record.setOrderNo(oOrderInfo.getOrderNo());
        record.setExpireAfterHour(vipGoods.getExpireAfterHour());
        record.setExpireDay(vipGoods.getExpireDay());
        if (StringUtils.isNotBlank(redeemCode)) {
            record.setStatus(0);
            record.setRedeemCode(redeemCode);
        } else {
            //status 2 生成兑换码失败
            record.setStatus(2);
            record.setRedeemCode("");
        }
        record.setStartTime(startDate);
        record.setEndTime(endDate);
        record.setCreatedTime(new Date());
        mongoTemplate.insert(record);
    }

    public void addFailRecord(OOrderInfo oOrderInfo) {
        Query query = new Query(Criteria.where("subOrderNo").is(oOrderInfo.getOOrderNo()));
        VipRedeemCodeFailRecord redeeCodeFailRecord = mongoTemplate.findOne(query, VipRedeemCodeFailRecord.class);
        if (redeeCodeFailRecord != null) {
            return;
        }
        redeeCodeFailRecord = new VipRedeemCodeFailRecord();
        redeeCodeFailRecord.setVirtualGoodsCode(oOrderInfo.getVirtualGoodsCode());
        redeeCodeFailRecord.setUserId(oOrderInfo.getAccountInfoId());
        redeeCodeFailRecord.setVirtualGoodsName(oOrderInfo.getVirtualGoodsName());
        redeeCodeFailRecord.setVirtualGoodsId(oOrderInfo.getVirtualGoodsId());
        redeeCodeFailRecord.setSubOrderNo(oOrderInfo.getOOrderNo());
        redeeCodeFailRecord.setOrderNo(oOrderInfo.getOrderNo());
        redeeCodeFailRecord.setCreatedTime(new Date());
        mongoTemplate.insert(redeeCodeFailRecord);
    }

    public VipRedeemCodeVo getRedeemCode(String subOrderNo, String userId, boolean isMobileLogin) {
        VipRedeemCodeRecord record = mongoTemplate.findOne(new Query(Criteria.where("subOrderNo").is(subOrderNo)), VipRedeemCodeRecord.class);
        if (record == null) {
            throw new BusinessException("兑换码信息不存在");
        }
        if (!isMobileLogin && !record.getUserId().equals(userId)) {
            throw new BusinessException("暂无权限查看");
        }
        if (record.getStatus() == 1) {
            throw new BusinessException("订单已退款，兑换码已作废");
        }
        if (record.getStatus() == 2) {
            throw new BusinessException("兑换码生成失败，请联系客服");
        }
        VipRedeemCodeVo vo = new VipRedeemCodeVo();
        Long time = record.getStartTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        long diff = time - System.currentTimeMillis();
        vo.setDiffTime(diff);
        vo.setExpireAfterHour(record.getExpireAfterHour());
        if (diff <= 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(THIRD_REDEE_CODE_URL);
            builder.append(record.getRedeemCode());
            vo.setUrl(builder.toString());
        }
        return vo;
    }
}
